/**
 * 
 */
package cn.edu.ujn.common.elasticSearch;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;

/**
 * @author 曹仁道
 * @类描述：ElasticSearch搜索引擎工具类
 */
public class ElasticSearchHandler {
	private Client client;
	public ElasticSearchHandler() {
		// 使用本机做为节点
		this("127.0.0.1");
	}

	public ElasticSearchHandler(String ipAddress) {
		// 集群连接超时设置
		/*try {
			client =TransportClient.builder().build().addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(ipAddress), 9200));
		} catch (Exception e) {
			e.printStackTrace();
		}*/
		
		Settings settings = Settings.settingsBuilder().put("cluster.name","my-application").put("client.transport.sniff", true).build();
		//TransportClient transportClient = TransportClient.builder().settings(settings).build().addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(ipAddress), 9300));
		//new InetSocketTransportAddress(InetAddress.getByName(ipAddress), "9300")
		try {
			client=TransportClient.builder().settings(settings).build().addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(ipAddress), 9300));
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 建立索引,索引建立好之后,会在elasticsearch-0.20.6\data\elasticsearch\nodes\0创建所以你看
	 * 
	 * @param indexName
	 *            为索引库名，一个es集群中可以有多个索引库。 名称必须为小写
	 * @param indexType
	 *            Type为索引类型，是用来区分同索引库下不同类型的数据的，一个索引库下可以有多个索引类型。
	 * @param jsondata
	 *            json格式的数据集合
	 * 
	 * @return
	 */
	public void createIndexResponse(String indexname, String type, List<String> jsondata) {
		// 创建索引库 需要注意的是.setRefresh(true)这里一定要设置,否则第一次建立索引查找不到数据
		IndexRequestBuilder requestBuilder = client.prepareIndex(indexname, type).setRefresh(true);
		for (int i = 0; i < jsondata.size(); i++) {
			requestBuilder.setSource(jsondata.get(i)).execute().actionGet();
		}

	}

	/**
	 * 创建索引
	 * 
	 * @param client
	 * @param jsondata
	 * @return
	 */
	public IndexResponse createIndexResponse(String indexname, String type, String jsondata) {
		IndexResponse response = client.prepareIndex(indexname, type).setSource(jsondata).execute().actionGet();
		return response;
	}

	/**
	 * 执行搜索
	 * @param <T>
	 * 
	 * @param queryBuilder
	 * @param indexname
	 * @param type
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public <T> List<T> searcher(QueryBuilder queryBuilder, String indexname, String type) {
		List<T> list = new ArrayList<T>();
		SearchResponse searchResponse = client.prepareSearch(indexname).setTypes(type).setQuery(queryBuilder).execute().actionGet();
		SearchHits hits = searchResponse.getHits();
		System.out.println("查询到记录数=" + hits.getTotalHits());
		SearchHit[] searchHists = hits.getHits();
		
		if (searchHists.length > 0) {
			for (SearchHit hit : searchHists) {
				Class<T> t;
				try {
					t = (Class<T>) Class.forName(type);
					Object instance=t.newInstance();
					//Field[] fields=t.getDeclaredFields();
					Method[] methods=t.getMethods();
					for(int i=0;i<methods.length;i++){
						Method m=methods[i];
						if(m.getName().contains("set")){
							String mName=m.getName();
							Class[] params = m.getParameterTypes();
							Class[] paramTypes = new Class[params.length];
							paramTypes[0] = Class.forName(params[0].getName());
							String temp=paramTypes[0].toString();
							String fName=mName.substring(3,mName.length());
							String pType=temp.substring((temp.lastIndexOf(".")+1), temp.length());
							if(pType.equals("String")){
								m.invoke(instance, new String[]{String.valueOf(hit.getSource().get(fName.toLowerCase()))});
							}else if(pType.equals("int")||pType.equals("Integer")){
								m.invoke(instance, new Integer[]{Integer.parseInt(String.valueOf(hit.getSource().get(fName.toLowerCase())))});
							}else if(pType.equals("long")||pType.equals("Long")){
								m.invoke(instance, new Long[]{Long.parseLong(String.valueOf(hit.getSource().get(fName.toLowerCase())))});
							}
						}
					}
					list.add((T)instance);
				} catch (ClassNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				} catch (InstantiationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return list;
	}
	
	 public static void main(String[] args) {
	        ElasticSearchHandler esHandler = new ElasticSearchHandler();
	        List<Medicine> mList=new ArrayList<Medicine>();
	        Medicine m=new Medicine();
	        m.setId((long) 8);
	        m.setName("测试结果");
	        m.setFunction("结果的测试");
	        mList.add(m);
	        List<String> jsondata = DataFactory.getInitJsonData(mList);
	        String indexname = "indexdemo";
	        String type = "cn.edu.ujn.common.elasticSearch.Medicine";
	        esHandler.createIndexResponse(indexname, type, jsondata);
	        //查询条件
	        QueryBuilder queryBuilder = QueryBuilders.termQuery("id", 8);//fuzzyQuery("name", "感冒");
	        List<Medicine> result = esHandler.searcher(queryBuilder, indexname, type);
	        System.out.println("查询到的结果："+result.size());
	        for(int i=0; i<result.size(); i++){
	            Medicine medicine = result.get(i);
	            System.out.println("(" + medicine.getId() + "):" +medicine.getName() + "\t" + medicine.getFunction());
	        }
	    }
}
